package visitor;

import symbol.ClassTable;
import symbol.MethodBodyTable;
import symbol.Symbol;
import symbol.SymbolTable;
import symbol.Table;
import syntaxtree.BooleanType;
import syntaxtree.ClassDeclExtends;
import syntaxtree.ClassDeclSimple;
import syntaxtree.Formal;
import syntaxtree.Identifier;
import syntaxtree.IdentifierType;
import syntaxtree.IntArrayType;
import syntaxtree.IntegerType;
import syntaxtree.MethodDecl;
import syntaxtree.Program;
import syntaxtree.Type;
import syntaxtree.VarDecl;

public class ImperativeSymbolTableVisitor implements TableSymbolVisitor {
	
	
	@Override
	public Table visit(Program n) {
		SymbolTable sT = new SymbolTable();
		ClassTable cT;
		cT = n.m.accept(this,Symbol.symbol(n.m.i1.toString()));
		sT.put(Symbol.symbol(n.m.i1.toString()), cT);			
	    for ( int i = 0; i < n.cl.size(); i++ ) {
	        cT = n.cl.elementAt(i).accept(this);
	        if(n.cl.elementAt(i) instanceof ClassDeclSimple){
	        	sT.put(Symbol.symbol(((ClassDeclSimple)n.cl.elementAt(i)).i.toString()), cT);
	        }
	        if(n.cl.elementAt(i) instanceof ClassDeclExtends){
	        	sT.put(Symbol.symbol(((ClassDeclExtends)n.cl.elementAt(i)).i.toString()), cT);
	        }	        
	    }
	    return sT;
	}

	@Override
	public Table visit(ClassDeclSimple n) {
		ClassTable cT = new ClassTable(Symbol.symbol(n.i.toString()));
		for (int i = 0; i < n.vl.size(); i++) {
			cT.fTable.put(Symbol.symbol(n.vl.elementAt(i).i.toString()), n.vl.elementAt(i).accept(this));
		}
		
		for (int i = 0; i < n.ml.size(); i++) {
			cT.methodCurrent=Symbol.symbol(n.ml.elementAt(i).i.s);
			cT.mTable.put(Symbol.symbol(n.ml.elementAt(i).i.toString()), n.ml.elementAt(i).accept(this));
		}
		cT.methodCurrent=null;
		return cT;
	}

	@Override
	public Table visit(ClassDeclExtends n) {
		ClassTable cT = new ClassTable(Symbol.symbol(n.i.toString()));
		cT.setExtendsClass(Symbol.symbol(n.j.toString()));
		for (int i = 0; i < n.vl.size(); i++) {
			cT.fTable.put(Symbol.symbol(n.vl.elementAt(i).i.toString()), n.vl.elementAt(i).accept(this));
		}
		
		for (int i = 0; i < n.ml.size(); i++) {
			cT.methodCurrent=Symbol.symbol(n.ml.elementAt(i).i.s);
			cT.mTable.put(Symbol.symbol(n.ml.elementAt(i).i.toString()), n.ml.elementAt(i).accept(this));
		}
		cT.methodCurrent=null;
		return cT;
	}

	@Override
	public Symbol visit(VarDecl n) {
		return Symbol.symbol(n.t.toString());
	}

	@Override
	public Table visit(MethodDecl n) {
		Symbol s;
		MethodBodyTable mBt = new  MethodBodyTable(Symbol.symbol(n.t.toString()),Symbol.symbol(n.i.toString()));
		for (int i = 0; i < n.fl.size(); i++) {
			s = (Symbol) n.fl.elementAt(i).accept(this);
			mBt.pTable.put(Symbol.symbol(n.fl.elementAt(i).i.toString()),s);
			mBt.pList.add(i, s);
		}
		//mBt.isInParams(false);
		for (int i = 0; i < n.vl.size(); i++) {
			mBt.lTable.put(Symbol.symbol(n.vl.elementAt(i).i.toString()),n.vl.elementAt(i).accept(this));
		}
		//mBt.isInParams(true);				
		return mBt;
	}

	@Override
	public Symbol visit(Formal n) {
		if(n.t instanceof BooleanType)return visit((BooleanType)n.t);
		if(n.t instanceof IdentifierType) return visit((IdentifierType)n.t);
		if(n.t instanceof IntArrayType) return visit((IntArrayType)n.t);
	    return visit((IntegerType)n.t);
	}

	@Override
	public Symbol visit(IntArrayType n) {
		return Symbol.symbol("int[]");
	}

	@Override
	public Symbol visit(BooleanType n) {
		return Symbol.symbol("boolean");
	}

	@Override
	public Symbol visit(IntegerType n) {
		return Symbol.symbol("int");
	}

	@Override
	public Symbol visit(IdentifierType n) {
		return Symbol.symbol(n.s);
	}
	
	@Override
	public Symbol visit(Identifier n) {
		return Symbol.symbol(n.s);
		
	}
	
	

	/*@Override
	public Table visit(Block n) {
		// TODO Auto-generated method stub

	}
/*
	@Override
	public Table visit(If n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(While n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(Print n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(Assign n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(ArrayAssign n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(And n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(LessThan n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(Plus n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(Minus n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(Times n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(ArrayLookup n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(ArrayLength n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(Call n) {
		// TODO Auto-generated method stub

	}

	

	@Override
	public Table visit(IdentifierExp n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(This n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(NewArray n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(NewObject n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(Not n) {
		// TODO Auto-generated method stub

	}
	@Override
	public Table visit(True n) {
		// TODO Auto-generated method stub

	}

	@Override
	public Table visit(False n) {
		// TODO Auto-generated method stub

	}
	
	@Override
	public Table visit(IntegerLiteral n) {
		// TODO Auto-generated method stub

	}
	*/

}
